#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

typedef struct
{
    char *ipv4addr;
    char *port;
}ThreadParams;

void *client(void *arg)
{
    ThreadParams *params = (ThreadParams *)arg;
    //创建UDP套接字
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    //准备好自己的地址
    struct sockaddr_in myaddr;
    bzero(&myaddr, sizeof(myaddr));
    myaddr.sin_family = AF_INET;
    myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    myaddr.sin_port = htons(atoi(params->port));
    //绑定本地IP地址
    bind(sockfd, (struct sockaddr *)&myaddr, sizeof(myaddr));

    char buf[128];
    struct sockaddr_in peeraddr;
    socklen_t len = sizeof(peeraddr);

    while(1)
    {
        bzero(&peeraddr, sizeof(peeraddr));
        bzero(buf, sizeof(buf));
        //等待对方打来的UDP数据报
        recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&peeraddr, &len);
        printf("[%s : %hu]-->%s", inet_ntoa(peeraddr.sin_addr), peeraddr.sin_port, buf);
    }
}

void *server(void *arg)
{
    ThreadParams *params = (ThreadParams *)arg;
    //创建UDP套接字
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    //准备好接受方的地址
    struct sockaddr_in peeraddr;
    bzero(&peeraddr, sizeof(peeraddr));
    peeraddr.sin_family = AF_INET;
    peeraddr.sin_addr.s_addr = inet_addr(params->ipv4addr);
    peeraddr.sin_port = htons(atoi(params->port));

    char buf[128];
    while(1)
    {
        bzero(&buf, sizeof(buf));
        fgets(buf, sizeof(buf), stdin);
        printf("[%s : %hu]", inet_ntoa(peeraddr.sin_addr), peeraddr.sin_port);
        //给对方发送UDP数据报
        sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&peeraddr, sizeof(peeraddr));
    }
}

int main(int argc, char const *argv[])
{
    if(argc != 3)
    {
        printf("argv[1] : sockaddr, argv [2] : post\n");
        exit(0);
    }
    ThreadParams *params = calloc(1,sizeof(ThreadParams));
    params->ipv4addr = (char *)argv[1];
    params->port     = (char *)argv[2];

    pthread_t tid1,tid2;
    pthread_create(&tid1, NULL, client, (void *)params);
    pthread_create(&tid2, NULL, server, (void *)params);

    pause();
    return 0;
}


